package com.lpf.testJVM;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleTest {

	static class ClassA {
		public void println(String s) {
			System.out.println(s);
		}
	}

	public static void main(String[] args) throws Throwable {
		Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
		/* 无论obj 最终是哪个实现类，下面这句都能正确调用到println方法 */
		getPrintlnMH(obj).invokeExact("icyfenix");
	}

	private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable {
		/*
		 * MethodType: 代表“方法类型”,包含了方法的返回值(methodType() 的第一个参数) 和 具体参数(methodType()
		 * 第二个及以后的参数)
		 */
		MethodType mt = MethodType.methodType(void.class, String.class);

		/*
		 * lookup() 方法来自于MethodHandles.lookup,这句的作用是在指定类中查找符合给定的 方法名称、方法类型，并且符合调用权限的方法句柄
		 */

		/*
		 * 因为这里调用的是一个虚方法，按照Java语言的规则，方法第一个参数是隐式的，代表该方
		 * 法的接收者,也即是this指向的对象，这个参数以前是放在参数列表中进行传递的，而现在提供了bindro()方 法来完成这件事情
		 */
		return MethodHandles.lookup().findVirtual(reveiver.getClass(), "println", mt).bindTo(reveiver);

	}
}